home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Resources
/
Chat & Communication
/
Digsby build 37
/
digsby_setup.exe
/
lib
/
mail
/
gmail.pyo
(
.txt
)
< prev
next >
Wrap
Python Compiled Bytecode
|
2008-10-13
|
16KB
|
475 lines
# Source Generated with Decompyle++
# File: in.pyo (Python 2.5)
from __future__ import with_statement
import re
import time
import urllib2
import cookielib
import threading
from threading import Lock
from urllib import urlencode
from datetime import datetime
from traceback import print_exc
from util.net import UrlQuery, GetDefaultHandlers, WebFormData
from util import threaded, scrape_clean, traceguard, EmailAddress, Storage
from mail import Email
from common import pref
from common.emailaccount import EmailAccount
from logging import getLogger
log = getLogger('gmail')
info = log.info
class Gmail(EmailAccount):
protocol = 'gmail'
baseAuthUrl = 'https://www.google.com'
authUrl = '/accounts/ClientLogin'
tokenUrl = '/accounts/IssueAuthToken'
messageIdMatcher = re.compile('message_id=([a-z0-9]+?)&')
jsredirectMatcher = re.compile('location\\.replace\\("(.*)"\\)')
default_domain = 'gmail.com'
def __init__(self, **k):
EmailAccount.__init__(self, **k)
self.token = ''
self.token_lock = threading.RLock()
self.datatoken = ''
self.updated_emails = None
self.updated_count = None
self.update_lock = Lock()
self.emailaddress = EmailAddress(self.name, 'gmail.com')
if self.emailaddress.domain in ('gmail.com', 'googlemail.com'):
self.baseMailUrl = '://mail.google.com/mail/'
else:
self.baseMailUrl = '://mail.google.com/a/' + self.emailaddress.domain + '/'
self.browser_http = 'https'
self.init_jar()
can_has_preview = True
def _reset_state(self):
self.init_jar()
self.token = self.datatoken = ''
self.sid = None
self.lsid = None
def browserBaseMailUrl(self):
return self.browser_http + self.baseMailUrl
browserBaseMailUrl = property(browserBaseMailUrl)
def internalBaseMailUrl(self):
return 'https' + self.baseMailUrl
internalBaseMailUrl = property(internalBaseMailUrl)
def init_jar(self):
self.jar = cookielib.CookieJar()
self.http_opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.jar), *GetDefaultHandlers())
self.http_opener.addheaders = [
('Content-type', 'application/x-www-form-urlencoded'),
('Cache-Control', 'no-cache')]
def url_token(self):
if self.web_login and self.token:
return dict(auth = self.token)
else:
return { }
url_token = property(url_token)
def inbox_url(self):
self.new_token()
return UrlQuery(self.browserBaseMailUrl, search = 'inbox', **self.url_token)
inbox_url = property(inbox_url)
def urlForEmail(self, email):
self.new_token()
return UrlQuery(self.browserBaseMailUrl, fs = '1', tf = '1', view = 'cv', search = 'all', th = str(email.id), **self.url_token)
def markAsRead(self, email):
EmailAccount.markAsRead(self, email)
self._do_action('read', email)
def archive(self, email):
EmailAccount.archive(self, email)
self._do_action('archive', email)
if pref('gmail.markive', False):
self.markAsRead(email)
def delete(self, email):
EmailAccount.delete(self, email)
self._do_action('delete', email)
def reportSpam(self, email):
EmailAccount.reportSpam(self, email)
self._do_action('spam', email)
def _do_action(self, action, email):
try:
self.gmail_at
except KeyError:
self.new_token(True)
(url, params) = self._actionUrl(action, email.id)
response = self.webrequest(url, **params)
log.debug_s('Action %r result: %r', action, response)
_do_action = threaded(_do_action)
def compose(self, to = '', subject = '', body = '', cc = '', bcc = ''):
extra = dict(fs = '1', view = 'cm')
su = subject
for name in 'to su body cc bcc'.split():
if vars()[name]:
extra[name] = vars()[name]
continue
self.new_token()
extra.update(self.url_token)
return UrlQuery(self.browserBaseMailUrl, **extra)
def _actionUrl(self, action, message_id):
action_names = dict(archive = 'rc_^i', delete = 'tr', read = 'rd', spam = 'sp')
if action not in action_names.values():
action = action_names[action]
url = UrlQuery(self.internalBaseMailUrl, ik = '', search = 'all', view = 'tl', start = '0')
params = dict(act = action, at = self.gmail_at, vp = '', msq = '', ba = 'false', t = message_id, fs = '1')
return (url, params)
def send_email(self, to = '', subject = '', body = '', cc = '', bcc = ''):
log.info('sending a mail')
data = dict(nvp_bu_send = 'Send')
for name in 'to subject body cc bcc'.split():
if vars()[name]:
data[name] = vars()[name].encode('utf-8')
continue
if not hasattr(self, 'sendpath'):
response = self.http_opener.open(self.internalBaseMailUrl + '?ui=html')
urlparse = urlparse
import urllib2
respurl = urlparse.urlparse(response.geturl())
try:
response.close()
except:
pass
del response
self.sendpath = respurl.path
url = 'https://mail.google.com' + self.sendpath
try:
at = self.gmail_at
except KeyError:
at = ''
params = dict(at = at, v = 'b', pv = 'tl', s = 's', fv = 'b', cpt = 'c', cs = 'c')
if not self.hosted:
params.update(fv = 'b', cpt = 'c', cs = 'c')
else:
params.update(cs = 'b', s = 's')
url = UrlQuery(url, params)
response = self.webrequest(url, follow_js_redirects = True, **data)
log.info('sent a mail')
log.info('send mail success: %r', bool('Your message has been sent.' in response))
return True
send_email = threaded(send_email)
def _get_notifier_data(self):
return self.webrequest(url = UrlQuery(self.internalBaseMailUrl, ui = 'pb'), data = WebFormData(auth = self.datatoken))
def hosted(self):
domain = self.emailaddress.domain
return None if domain != 'gmail.com' else None
hosted = property(hosted)
def authenticate(self, task = None):
try:
password = self._decryptedpw()
data = self.webrequest(self.baseAuthUrl + self.authUrl, data = WebFormData(Email = self.name, Passwd = password, accountType = 'HOSTED_OR_GOOGLE', service = 'mail'))
except (urllib2.HTTPError, urllib2.URLError):
e = None
if e.code == 403:
log.warning('Invalid username or password')
self.bad_pw(task)
return False
else:
log.warning('cannot authenticate gmail %s', self.name)
log.warning('data %s' % e.fp.read())
raise
except:
e.code == 403
if not data:
log.warning('No data from webrequest')
raise AssertionError('No data from webrequest')
if data.find('Error=badauth') != -1:
log.warning('Invalid username or password')
self.bad_pw(task)
return False
else:
log.debug('received token data: %r', data)
(sid, lsid, token) = data.split('\n')[:3]
self.sid = sid
self.lsid = lsid
self.datatoken = token.split('=')[1]
d = dict([
sid.split('='),
lsid.split('=')])
self.new_token(True)
return True
log.warning('unknown gmail error')
raise Exception('unknown gmail error')
def new_token(self, at = False):
self.token_lock.__enter__()
try:
sid = self.sid
lsid = self.lsid
d = dict([
sid.split('='),
lsid.split('=')])
self.getAuthToken(d, at)
finally:
pass
def getAuthToken(self, d, at = False):
d.update(service = 'mail')
token = self.webrequest(self.baseAuthUrl + self.tokenUrl, **d)
if not token:
log.debug('Error getting authtoken. state is: %s', self.state)
return None
self.token = token.strip()
if at:
self.get_gmail_at()
self.getAuthToken(d)
def get_gmail_at(self):
at_token = self.token
url = self.internalBaseMailUrl + '?auth=%s' % at_token
res = self.webrequest(url, follow_js_redirects = True)
try:
self.gmail_at
except KeyError:
log.debug('GMAIL_AT result: %r', res)
def gmail_at(self):
hosted = self.hosted
at_path = None if hosted else '/mail'
return self.jar._cookies['mail.google.com'][at_path]['GMAIL_AT'].value
gmail_at = property(gmail_at)
def update(self):
log.info('update at %s', time.ctime(time.time()))
EmailAccount.update(self)
self.real_update(success = self.finish_update, error = self.on_error)
def finish_update(self, updates):
if updates is sentinel:
log.warning('two updates were running at the same time')
return None
try:
(updated_emails, updated_count) = updates
except (TypeError, ValueError):
log.error('Update failed for %s, assuming auth error', self.name)
return None
log.info('%s got %d new messages %s', self, updated_count, time.ctime(time.time()))
self._received_emails(updated_emails[:25], updated_count)
def real_update(self):
if self.update_lock.acquire(False):
try:
if not self.token:
info('no auth token yet, authenticating')
if not self.authenticate():
log.info('auth failed, returning None from real_update')
return None
info('updating Gmail account %s at %s' % (self.name, time.ctime(time.time())))
(updated_emails, updated_count, _data) = parse_datapacks(self._get_notifier_data())
updated_emails = chunks_to_emails(updated_emails)
return (updated_emails, updated_count)
finally:
self.update_lock.release()
else:
return sentinel
real_update = threaded(real_update)
def webrequest(self, url, data = '', follow_js_redirects = False, **kwparams):
try:
response = self.http_opener.open(url, data + urlencode(kwparams.items()))
resp = response.read()
if follow_js_redirects:
match = self.jsredirectMatcher.search(resp)
if match:
new_url = match.groups()[0]
response = self.http_opener.open(self.baseAuthUrl + new_url)
resp = response.read()
return resp
except (urllib2.HTTPError, urllib2.URLError):
e = None
if getattr(e, 'code', None) == 403:
log.warning('Invalid username or password')
self.bad_pw()
return False
else:
print_exc()
import sys as sys
print >>sys.stderr, 'url: %s' % url
except Exception:
e = None
print_exc()
return False
from util import utf7_to_int as u7i
def chunk_datapack(data):
data = data[1:]
(num, numbytes) = u7i(data)
data = data[numbytes:]
return (data[:num], data[num:])
def get_chunk(data):
(type_, numbytes) = u7i(data)
data = data[numbytes:]
if type_ == 184:
(value, length_) = u7i(data)
elif type_ == 152:
(value, length_) = u7i(data)
else:
(length_, numbytes) = u7i(data)
data = data[numbytes:]
return (type_, data[:length_], data[length_:])
def get_mid_date(data):
orig_length = len(data)
(length_, numbytes) = u7i(data)
expected_length = orig_length - length_ - numbytes
data = data[numbytes:]
(msgid, numbytes) = u7i(data)
data = data[numbytes:]
(_unknown, numbytes) = u7i(data)
data = data[numbytes:]
(time_in_ms, numbytes) = u7i(data)
data = data[numbytes:]
return (msgid, time_in_ms, data)
from collections import defaultdict
def parse_chunk(chunk):
retval = defaultdict(list)
(mid, time_in_ms, data) = get_mid_date(chunk)
retval['mid'] = mid
retval['time'] = time_in_ms
while data:
(t, v, data) = get_chunk(data)
if t == 146:
v = parse_from(v)
elif t == 184:
v = u7i(v)[0]
retval[t].append(v)
return retval
def chunks_to_emails(dictionaries):
return [ dict_to_email(e) for e in dictionaries ]
def parse_datapacks(data):
retval = []
while data[0] == '\n':
(chunk, data) = chunk_datapack(data)
retval.append(parse_chunk(chunk))
num_messages = 0
(type_, numbytes) = u7i(data)
data = data[numbytes:]
if type_ == 136:
(num_messages, numbytes) = u7i(data)
data = data[numbytes:]
return (retval, num_messages, data)
def parse_from(from_):
retval = { }
from_ = from_[1:]
(retval['mystery_bytes1'], from_) = from_.split('\n', 1)
(length_, numbytes) = u7i(from_)
from_ = from_[numbytes:]
retval['email_addr'] = from_[:length_]
from_ = from_[length_:]
(type_, numbytes) = u7i(from_)
if type_ == 18:
from_ = from_[numbytes:]
(length_, numbytes) = u7i(from_)
from_ = from_[numbytes:]
retval['from_text'] = from_[:length_]
from_ = from_[length_:]
retval['remainder_bytes'] = from_
return retval
decode = lambda s: scrape_clean(s.decode('utf-8'))
def dict_to_email(d):
k = Storage(labels = 130, author = 146, subject = 162, snippet = 170, attachments = 178)
msgid = d['mid']
author_email = d[k.author][-1]['email_addr']
author_name = decode(d[k.author][-1].get('from_text', ''))
subject = decode(d[k.subject][-1])
snippet = decode(d[k.snippet][-1])
attachments = [ Storage(name = a) for a in d[k.attachments] ]
labels = _[2]
return Email(id = '%x' % msgid, fromname = author_name, fromemail = author_email, sendtime = datetime.fromtimestamp(d['time'] // 1000), subject = subject, content = snippet, attachments = attachments, labels = labels)